;******************************************** ;*Written By: MSH * ;*Date: 06/09/06 * ;*Version: 1.0 * ;*Project Name: Simple PIC Clock * ;*Microprocessor: PIC16F84A * ;*Clock Frequency: 8 MHz * ;******************************************** ;PROGRAM FUNCTION: PICMCU controlled clock ; with 4 digit display. list P=16F84A include p16F84A.inc ;========================================= ;Declarations: porta equ 05 portb equ 06 mark125 equ 0C post30 equ 0D post125 equ 0E minutes equ 0F tensmins equ 10 hours equ 11 tenshours equ 12 twentyfour equ 13 org 0 goto start ;========================================= ;Subroutines: Init clrf porta ;resets I/O ports clrf portb bsf STATUS,5 ; selects bank 1. movlw b'10000' ; RA0-3: D1 to D4 on 4_Digit LCD, movwf TRISA ; RA4: Clk_Adjust. movlw b'00000000' ; RB0: DP, RA1-7: A to G. movwf TRISB ; movlw b'00000111' ; TMR0 prescaled by 256 movwf OPTION_REG ; pull ups disabled. bcf STATUS,5 ; selects bank 0. movlw b'00000000' ; disables all interrupts. movwf INTCON ; movlw d'125' ; moves the decimal No125 into the GPF called movwf mark125 ; mark125, the marker for TwoSecs. call resetpost30 ; call resetpost125 ; clrf minutes ; clrf tensmins ; clrf hours ; clrf tenshours ; clrf twentyfour ; retlw 0 resetpost30 movlw d'30' ; resets post30 by moving the No30 back into it. movwf post30 ; return ; returns from subroutine. resetpost125 movlw d'125' ; resets post125 by moving the No125 back into it. movwf post125 ; return ; returns from subroutine. _7SegDisp addwf PCL,f ; skips to relavent instruction. retlw b'10111111' ; code for 0 retlw b'10110000' ; code for 1 retlw b'11011011' ; code for 2 retlw b'11111001' ; code for 3 retlw b'11110100' ; code for 4 retlw b'11101101' ; code for 5 retlw b'11101111' ; code for 6 retlw b'10111000' ; code for 7 retlw b'11111111' ; code for 8 retlw b'11111101' ; code for 9 timer movfw mark125 ; tests to see if TMR0 has passed subwf TMR0,w ; through 125 cycles. btfss STATUS,Z ; retlw 0 ; movlw d'125' ; 1/10th of a second has passed, so adds addwf mark125,f ; the decimal 125 to Mark125 decfsz post125,f ; has 2 secs passed? retlw 0 ; Returns from Subroutine. call resetpost125 ; decfsz post30,f ; has 1 minute passed? retlw 0 ; 1 minute hasn't passed so returns from Subroutine. call resetpost30 ; incf minutes,f ; increments the number of minutes. movlw d'10' ; tests to see whether minutes has subwf minutes,w ; reached 10. (i.e has 10 minutes passed?) btfss STATUS,Z ; retlw 0 ; 10 minutes haven't passed so returns from Subroutine. clrf minutes ; Ten minutes has passed so resets minutes incf tensmins,f ; and increments tensmins by one. movlw d'6' ; tests to see whether tensmins has subwf tensmins,w ; reached 6. (i.e has 1 hour passed?) btfss STATUS,Z ; retlw 0 ; 1 hour hasn't passed so returns from Subroutine. clrf tensmins ; 1 hour has passed so resets tensmins btfsc twentyfour,0 ; goto twenty4 ; incf hours,f ; and increments hours by one. movlw d'10' ; Tests to see whether hours has subwf hours,w ; reached 10. (i.e have 10 hours passed?) btfss STATUS,Z ; retlw 0 ; 10 hours haven't passed so returns from Subroutine. clrf hours ; 10 hours have passed so resets hours incf tenshours,f ; and increments tenshours by one. movlw d'2' ; Tests to see whether tenshours has subwf tenshours,w ; reached 2. (i.e have 12 hours passed?). btfss STATUS,Z ; retlw 0 ; 20 hours haven't passed so returns from Subroutine. clrf hours ; bsf twentyfour,0 ; retlw 0 ; twenty4 incf hours,f ; movlw d'4' ; subwf hours,w ; btfss STATUS,Z ; retlw 0 ; clrf hours ; clrf tenshours ; bcf twentyfour,0 ; retlw 0 ; 24 hours have passed so returns from Subroutine. display movlw b'00000011' ; ignores all but bits 0 and 1 of TMR0 andwf TMR0,w ; leaving the result in the working register addwf PCL,f ; Adds the result to the program counter goto display1m ; displays minutes goto display10m ; displays tens of minutes goto display1h ; displays hours goto display10h ; displays tens of hours display1m movfw minutes ; takes the number out of minutes call _7SegDisp ; converts the number into 7 Seg. code movwf portb ; displays the value through Port B movlw b'0010' ; turns on correct display movwf porta ; retlw 0 display10m movfw tensmins ; takes the number out of tenmins call _7SegDisp ; converts the number into 7 Seg code movwf portb ; displays the value through port B movlw b'0001' ; turns on correct display movwf porta ; retlw 0 display1h movfw hours ; takes the number out of hours call _7SegDisp ; converts the number into 7 Seg code movwf portb ; displays the value through port B movlw b'0100' ; turns on correct display movwf porta ; retlw 0 display10h movfw tenshours ; takes the number out of tenshours call _7SegDisp ; converts the number into 7 Seg code movwf portb ; displays the value through port B movlw b'1000' ; turns on correct display movwf porta ; retlw 0 tchange call resetpost125 ; call resetpost30 ; incf minutes,f ; movlw d'10' ; tests to see whether minutes has subwf minutes,w ; reached 10. (i.e has 10 minutes passed?) btfss STATUS,Z ; retlw 0 ; clrf minutes ; incf tensmins,f ; movlw d'6' ; tests to see whether tensmins has subwf tensmins,w ; reached 6. (i.e has 1 hour passed?) btfss STATUS,Z ; retlw 0 ; clrf tensmins ; btfsc twentyfour,0 ; goto twenty4a ; incf hours,f ; movlw d'10' ; Tests to see whether hours has subwf hours,w ; reached 10. (i.e have 10 hours passed?) btfss STATUS,Z ; retlw 0 ; clrf hours ; incf tenshours,f ; and increments tenshours by one. movlw d'2' ; Tests to see whether tenshours has subwf tenshours,w ; reached 2. (i.e have 12 hours passed?). btfss STATUS,Z ; retlw 0 ; 20 hours haven't passed so returns from Subroutine. clrf hours ; bsf twentyfour,0 ; retlw 0 twenty4a incf hours,f ; movlw d'4' ; subwf hours,w ; btfss STATUS,Z ; retlw 0 ; clrf hours ; clrf tenshours ; bcf twentyfour,0 ; retlw 0 ; ;========================================= ;Program Start: start call Init main call timer ; call display ; btfss porta,4 ; goto main ; release call timer ; call display ; btfsc porta,4 ; goto release ; call tchange ; goto main ; end